/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * vim: set ts=8 sts=4 et sw=4 tw=99: */// Copyright 2012 the V8 project authors. All rights reserved.// Redistribution and use in source and binary forms, with or without// modification, are permitted provided that the following conditions are// met://// * Redistributions of source code must retain the above copyright// notice, this list of conditions and the following disclaimer.// * Redistributions in binary form must reproduce the above// copyright notice, this list of conditions and the following// disclaimer in the documentation and/or other materials provided// with the distribution.// * Neither the name of Google Inc. nor the names of its// contributors may be used to endorse or promote products derived// from this software without specific prior written permission.//// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.#include"irregexp/RegExpMacroAssembler.h"#include"irregexp/RegExpBytecode.h"usingnamespacejs;usingnamespacejs::irregexp;template<typenameCharT>intirregexp::CaseInsensitiveCompareStrings(constCharT*substring1,constCharT*substring2,size_tbyteLength){MOZ_ASSERT(byteLength%sizeof(CharT)==0);size_tlength=byteLength/sizeof(CharT);for(size_ti=0;i<length;i++){char16_tc1=substring1[i];char16_tc2=substring2[i];if(c1!=c2){c1=unicode::ToLowerCase(c1);c2=unicode::ToLowerCase(c2);if(c1!=c2)return0;}}return1;}templateintirregexp::CaseInsensitiveCompareStrings(constLatin1Char*substring1,constLatin1Char*substring2,size_tbyteLength);templateintirregexp::CaseInsensitiveCompareStrings(constchar16_t*substring1,constchar16_t*substring2,size_tbyteLength);template<typenameCharT>intirregexp::CaseInsensitiveCompareUCStrings(constCharT*substring1,constCharT*substring2,size_tbyteLength){MOZ_ASSERT(byteLength%sizeof(CharT)==0);size_tlength=byteLength/sizeof(CharT);for(size_ti=0;i<length;i++){char16_tc1=substring1[i];char16_tc2=substring2[i];if(c1!=c2){c1=unicode::FoldCase(c1);c2=unicode::FoldCase(c2);if(c1!=c2)return0;}}return1;}templateintirregexp::CaseInsensitiveCompareUCStrings(constLatin1Char*substring1,constLatin1Char*substring2,size_tbyteLength);templateintirregexp::CaseInsensitiveCompareUCStrings(constchar16_t*substring1,constchar16_t*substring2,size_tbyteLength);InterpretedRegExpMacroAssembler::InterpretedRegExpMacroAssembler(JSContext*cx,LifoAlloc*alloc,RegExpShared*shared,size_tnumSavedRegisters):RegExpMacroAssembler(cx,*alloc,shared,numSavedRegisters),pc_(0),advance_current_start_(0),advance_current_offset_(0),advance_current_end_(kInvalidPC),buffer_(nullptr),length_(0){// The first int32 word is the number of registers.Emit32(0);}InterpretedRegExpMacroAssembler::~InterpretedRegExpMacroAssembler(){js_free(buffer_);}RegExpCodeInterpretedRegExpMacroAssembler::GenerateCode(JSContext*cx,boolmatch_only){Bind(&backtrack_);Emit(BC_POP_BT,0);// Update the number of registers.*(int32_t*)buffer_=num_registers_;RegExpCoderes;res.byteCode=buffer_;buffer_=nullptr;returnres;}voidInterpretedRegExpMacroAssembler::AdvanceCurrentPosition(intby){MOZ_ASSERT(by>=kMinCPOffset);MOZ_ASSERT(by<=kMaxCPOffset);advance_current_start_=pc_;advance_current_offset_=by;Emit(BC_ADVANCE_CP,by);advance_current_end_=pc_;}voidInterpretedRegExpMacroAssembler::AdvanceRegister(intreg,intby){checkRegister(reg);Emit(BC_ADVANCE_REGISTER,reg);Emit32(by);}voidInterpretedRegExpMacroAssembler::Backtrack(){Emit(BC_POP_BT,0);}voidInterpretedRegExpMacroAssembler::Bind(jit::Label*label){advance_current_end_=kInvalidPC;MOZ_ASSERT(!label->bound());if(label->used()){intpos=label->offset();while(pos!=jit::Label::INVALID_OFFSET){intfixup=pos;pos=*reinterpret_cast<int32_t*>(buffer_+fixup);*reinterpret_cast<uint32_t*>(buffer_+fixup)=pc_;}}label->bind(pc_);}voidInterpretedRegExpMacroAssembler::CheckAtStart(jit::Label*on_at_start){Emit(BC_CHECK_AT_START,0);EmitOrLink(on_at_start);}voidInterpretedRegExpMacroAssembler::CheckCharacter(unsignedc,jit::Label*on_equal){if(c>MAX_FIRST_ARG){Emit(BC_CHECK_4_CHARS,0);Emit32(c);}else{Emit(BC_CHECK_CHAR,c);}EmitOrLink(on_equal);}voidInterpretedRegExpMacroAssembler::CheckCharacterAfterAnd(unsignedc,unsignedand_with,jit::Label*on_equal){if(c>MAX_FIRST_ARG){Emit(BC_AND_CHECK_4_CHARS,0);Emit32(c);}else{Emit(BC_AND_CHECK_CHAR,c);}Emit32(and_with);EmitOrLink(on_equal);}voidInterpretedRegExpMacroAssembler::CheckCharacterGT(char16_tlimit,jit::Label*on_greater){Emit(BC_CHECK_GT,limit);EmitOrLink(on_greater);}voidInterpretedRegExpMacroAssembler::CheckCharacterLT(char16_tlimit,jit::Label*on_less){Emit(BC_CHECK_LT,limit);EmitOrLink(on_less);}voidInterpretedRegExpMacroAssembler::CheckGreedyLoop(jit::Label*on_tos_equals_current_position){Emit(BC_CHECK_GREEDY,0);EmitOrLink(on_tos_equals_current_position);}voidInterpretedRegExpMacroAssembler::CheckNotAtStart(jit::Label*on_not_at_start){Emit(BC_CHECK_NOT_AT_START,0);EmitOrLink(on_not_at_start);}voidInterpretedRegExpMacroAssembler::CheckNotBackReference(intstart_reg,jit::Label*on_no_match){MOZ_ASSERT(start_reg>=0);MOZ_ASSERT(start_reg<=kMaxRegister);Emit(BC_CHECK_NOT_BACK_REF,start_reg);EmitOrLink(on_no_match);}voidInterpretedRegExpMacroAssembler::CheckNotBackReferenceIgnoreCase(intstart_reg,jit::Label*on_no_match,boolunicode){MOZ_ASSERT(start_reg>=0);MOZ_ASSERT(start_reg<=kMaxRegister);if(unicode)Emit(BC_CHECK_NOT_BACK_REF_NO_CASE_UNICODE,start_reg);elseEmit(BC_CHECK_NOT_BACK_REF_NO_CASE,start_reg);EmitOrLink(on_no_match);}voidInterpretedRegExpMacroAssembler::CheckNotCharacter(unsignedc,jit::Label*on_not_equal){if(c>MAX_FIRST_ARG){Emit(BC_CHECK_NOT_4_CHARS,0);Emit32(c);}else{Emit(BC_CHECK_NOT_CHAR,c);}EmitOrLink(on_not_equal);}voidInterpretedRegExpMacroAssembler::CheckNotCharacterAfterAnd(unsignedc,unsignedand_with,jit::Label*on_not_equal){if(c>MAX_FIRST_ARG){Emit(BC_AND_CHECK_NOT_4_CHARS,0);Emit32(c);}else{Emit(BC_AND_CHECK_NOT_CHAR,c);}Emit32(and_with);EmitOrLink(on_not_equal);}voidInterpretedRegExpMacroAssembler::CheckNotCharacterAfterMinusAnd(char16_tc,char16_tminus,char16_tand_with,jit::Label*on_not_equal){Emit(BC_MINUS_AND_CHECK_NOT_CHAR,c);Emit16(minus);Emit16(and_with);EmitOrLink(on_not_equal);}voidInterpretedRegExpMacroAssembler::CheckCharacterInRange(char16_tfrom,char16_tto,jit::Label*on_in_range){Emit(BC_CHECK_CHAR_IN_RANGE,0);Emit16(from);Emit16(to);EmitOrLink(on_in_range);}voidInterpretedRegExpMacroAssembler::CheckCharacterNotInRange(char16_tfrom,char16_tto,jit::Label*on_not_in_range){Emit(BC_CHECK_CHAR_NOT_IN_RANGE,0);Emit16(from);Emit16(to);EmitOrLink(on_not_in_range);}voidInterpretedRegExpMacroAssembler::CheckBitInTable(uint8_t*table,jit::Label*on_bit_set){staticconstintkBitsPerByte=8;Emit(BC_CHECK_BIT_IN_TABLE,0);EmitOrLink(on_bit_set);for(inti=0;i<kTableSize;i+=kBitsPerByte){intbyte=0;for(intj=0;j<kBitsPerByte;j++){if(table[i+j]!=0)byte|=1<<j;}Emit8(byte);}}voidInterpretedRegExpMacroAssembler::JumpOrBacktrack(jit::Label*to){if(advance_current_end_==pc_){// Combine advance current and goto.pc_=advance_current_start_;Emit(BC_ADVANCE_CP_AND_GOTO,advance_current_offset_);EmitOrLink(to);advance_current_end_=kInvalidPC;}else{// Regular goto.Emit(BC_GOTO,0);EmitOrLink(to);}}voidInterpretedRegExpMacroAssembler::Fail(){Emit(BC_FAIL,0);}voidInterpretedRegExpMacroAssembler::IfRegisterGE(intreg,intcomparand,jit::Label*if_ge){checkRegister(reg);Emit(BC_CHECK_REGISTER_GE,reg);Emit32(comparand);EmitOrLink(if_ge);}voidInterpretedRegExpMacroAssembler::IfRegisterLT(intreg,intcomparand,jit::Label*if_lt){checkRegister(reg);Emit(BC_CHECK_REGISTER_LT,reg);Emit32(comparand);EmitOrLink(if_lt);}voidInterpretedRegExpMacroAssembler::IfRegisterEqPos(intreg,jit::Label*if_eq){checkRegister(reg);Emit(BC_CHECK_REGISTER_EQ_POS,reg);EmitOrLink(if_eq);}voidInterpretedRegExpMacroAssembler::LoadCurrentCharacter(intcp_offset,jit::Label*on_end_of_input,boolcheck_bounds,intcharacters){MOZ_ASSERT(cp_offset>=kMinCPOffset);MOZ_ASSERT(cp_offset<=kMaxCPOffset);intbytecode;if(check_bounds){if(characters==4){bytecode=BC_LOAD_4_CURRENT_CHARS;}elseif(characters==2){bytecode=BC_LOAD_2_CURRENT_CHARS;}else{MOZ_ASSERT(characters==1);bytecode=BC_LOAD_CURRENT_CHAR;}}else{if(characters==4){bytecode=BC_LOAD_4_CURRENT_CHARS_UNCHECKED;}elseif(characters==2){bytecode=BC_LOAD_2_CURRENT_CHARS_UNCHECKED;}else{MOZ_ASSERT(characters==1);bytecode=BC_LOAD_CURRENT_CHAR_UNCHECKED;}}Emit(bytecode,cp_offset);if(check_bounds)EmitOrLink(on_end_of_input);}voidInterpretedRegExpMacroAssembler::PopCurrentPosition(){Emit(BC_POP_CP,0);}voidInterpretedRegExpMacroAssembler::PopRegister(intreg){checkRegister(reg);Emit(BC_POP_REGISTER,reg);}voidInterpretedRegExpMacroAssembler::PushCurrentPosition(){Emit(BC_PUSH_CP,0);}voidInterpretedRegExpMacroAssembler::PushRegister(intreg,StackCheckFlagcheck_stack_limit){checkRegister(reg);Emit(BC_PUSH_REGISTER,reg);}voidInterpretedRegExpMacroAssembler::ReadCurrentPositionFromRegister(intreg){checkRegister(reg);Emit(BC_SET_CP_TO_REGISTER,reg);}voidInterpretedRegExpMacroAssembler::ReadBacktrackStackPointerFromRegister(intreg){checkRegister(reg);Emit(BC_SET_SP_TO_REGISTER,reg);}voidInterpretedRegExpMacroAssembler::SetCurrentPositionFromEnd(intby){MOZ_ASSERT(by>=0&&by<(1<<24));Emit(BC_SET_CURRENT_POSITION_FROM_END,by);}voidInterpretedRegExpMacroAssembler::SetRegister(intreg,intto){checkRegister(reg);Emit(BC_SET_REGISTER,reg);Emit32(to);}boolInterpretedRegExpMacroAssembler::Succeed(){Emit(BC_SUCCEED,0);// Restart matching for global regexp not supported.returnfalse;}voidInterpretedRegExpMacroAssembler::WriteCurrentPositionToRegister(intreg,intcp_offset){checkRegister(reg);Emit(BC_SET_REGISTER_TO_CP,reg);Emit32(cp_offset);// Current position offset.}voidInterpretedRegExpMacroAssembler::ClearRegisters(intreg_from,intreg_to){MOZ_ASSERT(reg_from<=reg_to);for(intreg=reg_from;reg<=reg_to;reg++)SetRegister(reg,-1);}voidInterpretedRegExpMacroAssembler::WriteBacktrackStackPointerToRegister(intreg){checkRegister(reg);Emit(BC_SET_REGISTER_TO_SP,reg);}voidInterpretedRegExpMacroAssembler::PushBacktrack(jit::Label*label){Emit(BC_PUSH_BT,0);EmitOrLink(label);}voidInterpretedRegExpMacroAssembler::BindBacktrack(jit::Label*label){Bind(label);}voidInterpretedRegExpMacroAssembler::EmitOrLink(jit::Label*label){if(label==nullptr)label=&backtrack_;if(label->bound()){Emit32(label->offset());}else{intpos=label->use(pc_);Emit32(pos);}}voidInterpretedRegExpMacroAssembler::Emit(uint32_tbyte,uint32_ttwenty_four_bits){uint32_tword=((twenty_four_bits<<BYTECODE_SHIFT)|byte);Emit32(word);}voidInterpretedRegExpMacroAssembler::Emit32(uint32_tword){MOZ_ASSERT(pc_<=length_);if(pc_+3>=length_)Expand();*reinterpret_cast<uint32_t*>(buffer_+pc_)=word;pc_+=4;}voidInterpretedRegExpMacroAssembler::Emit16(uint32_tword){MOZ_ASSERT(pc_<=length_);if(pc_+1>=length_)Expand();*reinterpret_cast<uint16_t*>(buffer_+pc_)=word;pc_+=2;}voidInterpretedRegExpMacroAssembler::Emit8(uint32_tword){MOZ_ASSERT(pc_<=length_);if(pc_==length_)Expand();*reinterpret_cast<unsignedchar*>(buffer_+pc_)=word;pc_+=1;}voidInterpretedRegExpMacroAssembler::Expand(){AutoEnterOOMUnsafeRegionoomUnsafe;intnewLength=Max(100,length_*2);if(newLength<length_+4)oomUnsafe.crash("InterpretedRegExpMacroAssembler::Expand");buffer_=(uint8_t*)js_realloc(buffer_,newLength);if(!buffer_)oomUnsafe.crash("InterpretedRegExpMacroAssembler::Expand");length_=newLength;}